<?php
namespace core\models;
/**
 * cUrl处理类
 * @package core\models
 * @author  ZhouHaoHua <53027327@qq.com>
 * @package
 */
class Curl {
    /**
     * 返回一个cURL句柄，供curl_setopt(), curl_exec()和curl_close() 函数使用。
     * @var resource
     */
    private $ch;
    private $url;

    /**
     * 初始化
     * @param string|null $url 目标URL
     */
    public function __construct($url = null) {
        $this->url = $url;
        $this->ch  = curl_init($url);
    }

    /**
     * 设置超时时间
     * @param int  $limit 时间数，默认为2秒
     * @param bool $ms    设置为毫秒，若此值为false则为秒
     * @return bool
     */
    public function timeOut($limit = 2, $ms = false) {
        if ($ms) {
            return $this->setopt(CURLOPT_TIMEOUT_MS, $limit);
        }
        return $this->setopt(CURLOPT_TIMEOUT, $limit);
    }

    /**
     * 设置cURL传输选项。实现curl_setopt或curl_setopt_array的功能
     * @param array $options 要设置的选项。一个array用来确定将被设置的选项及其值。数组的键值必须是一个有效的curl_setopt()常量或者是它们对等的整数值。
     * @see http://php.net/manual/zh/function.curl-setopt-array.php
     * @return bool
     */
    public function setopt_array(array $options) {
        return curl_setopt_array($this->ch, $options);
    }

    /**
     * 设置目标URL地址
     * @param string $url 网址
     * @return bool
     */
    public function setUrl($url) {
        $this->url = $url;
        return $this->setopt(CURLOPT_URL, $url);
    }

    /**
     * 设置一个cURL传输选项
     * @param int   $option 需要设置的CURLOPT_XXX选项
     * @param mixed $value  将设置在option选项上的值
     * @see http://php.net/manual/zh/function.curl-setopt.php
     * @return bool
     */
    public function setopt($option, $value) {
        return curl_setopt($this->ch, $option, $value);
    }

    /**
     * 执行一个cURL会话
     * @param int $CURLOPT_RETURNTRANSFER 如果该选项被设置为1将返回执行的原生数据结果
     * @return bool 成功时返回 TRUE， 或者在失败时返回 FALSE。 如果 CURLOPT_RETURNTRANSFER 选项被设置，函数执行成功时会返回执行的结果，失败时返回 FALSE 。
     */
    public function exec($CURLOPT_RETURNTRANSFER = 1) {
        if ($CURLOPT_RETURNTRANSFER == 1) {
            $this->setopt(CURLOPT_RETURNTRANSFER, 1);
        }
        return curl_exec($this->ch);
    }

    /**
     * 设置cookie的保存和读取的文件地址
     * @param $cookieFile 要保存cookie的文件地址，可不需要扩展名。如：/tmp/CookieFile
     * @return bool
     */
    public function setCookieFile($cookieFile) {
        $options = array(
            CURLOPT_COOKIESESSION => 1,
            CURLOPT_COOKIEJAR     => $cookieFile,
            CURLOPT_COOKIEFILE    => $cookieFile,
        );
        return $this->setopt_array($options);
    }

    /**
     * POST提交数据信息
     * @param array $data 。支持多维数组
     * @return bool 注意这一步执行之后还要调用::exec()方法才能取回结果
     */
    public function submitPost($data = array()) {
        $options = array(
            CURLOPT_POST       => 1,
            CURLOPT_POSTFIELDS => http_build_query($data)
        );
        if (stripos($this->url, 'https') === 0) {
            $options[CURLOPT_SSL_VERIFYHOST] = 0;
            $options[CURLOPT_SSL_VERIFYPEER] = 0;
        }
        return $this->setopt_array($options);
    }

    /**
     * GET提交数据信息
     * @param array $data 支持多维数组
     * @return bool 注意这一步执行之后还要调用::exec()方法才能取回结果。此方法未测试，可能会有些问题！
     * @author ZhouHaoHua <53027327@qq.com>
     */
    public function submitGet($data = array()) {
        if ($data) {
            if (strpos($this->url, '?')) {
                $this->url .= "&" . http_build_query($data);
            } else {
                $this->url .= "?" . http_build_query($data);
            }
        }
        $this->setUrl($this->url);
        $options = array(
            CURLOPT_POST => 0
        );
        if (stripos($this->url, 'https') === 0) {
            $options = array(
                CURLOPT_POST           => 0,
                CURLOPT_SSL_VERIFYHOST => 0,
                CURLOPT_SSL_VERIFYPEER => 0,
            );
        }
        return $this->setopt_array($options);
    }
    /**
     * POST提交JSON格式的数据信息
     * @param string $data json_encode之后的字符串
     * @return bool
     * @author 袁水红
     */
    public function submitJsonPost($data){
        $options = array(
            CURLOPT_POST       => 1,
            CURLOPT_POSTFIELDS => $data
        );
        if (stripos($this->url, 'https') === 0) {
            $options[CURLOPT_SSL_VERIFYHOST] = 0;
            $options[CURLOPT_SSL_VERIFYPEER] = 0;
        }
        return $this->setopt_array($options);
    }
    /**
     * 设置采用http验证方式时的用户和密码
     * 注意：使用前要先用setCookieFile()设置cookie文件路径
     * @param string $username 用户名
     * @param string $password 密码
     * @return bool
     */
    public function setHttpAuth($username, $password) {
        $options = array(
            CURLOPT_HTTPAUTH => CURLAUTH_ANY,
            CURLOPT_USERPWD  => "$username:$password"
        );
        return $this->setopt_array($options);
    }

    /**
     * 设置http请求头信息
     * @param array $headers 请求的头数据(二维数组)。如['Accept' => "application/json", 'Host' => "act.qzone.qq.com"]
     * @return bool
     * @author ZhouHaoHua <53027327@qq.com>
     */
    public function setHttpHeader($headers = array()){
        if($headers) {
            $h = array();
            foreach($headers as $name => $value){
                $h[] = $name.': '.$value;
            }
            return curl_setopt($this->ch, CURLOPT_HTTPHEADER, $h);
        }
        return false;
    }

    /**
     * 获取一个cURL连接资源句柄的信息
     * @param int $opt
     * @see http://php.net/manual/zh/function.curl-getinfo.php
     * @return mixed
     */
    public function getInfo($opt = 0) {
        return curl_getinfo($this->ch, $opt);
    }

    /**
     * 返回最后一次的错误号
     * @return int
     */
    public function errno() {
        return curl_errno($this->ch);
    }

    /**
     * 返回当前会话最近一次错误的字符串
     * @return string
     */
    public function error() {
        return curl_error($this->ch);
    }

    /**
     * 析构
     */
    public function __destruct() {
        //echo '__destruct';
        if(is_resource($this->ch))
            curl_close($this->ch);
    }

}